package com.hxrk.cecardvr;

import android.graphics.Bitmap;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.os.Build;
import android.util.Log;

import com.hxrk.easyface.EasyFace;
import com.hxrk.jni.Mp4v2Native;

import org.opencv.core.CvType;
import org.opencv.core.Mat;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

/**
 * 人脸识别数据传输服务端线程
 */
public class FaceServerThread extends Thread {
    private final static String TAG = "FaceServerThread";
    public static String SOCKET_ADDRESS = "local.socket.address.server";//

    LocalServerSocket server = null;

    private boolean connNet = false;

    public FaceServerThread() {
    }

    @Override
    public void run() {
        init();
    }

    public void init() {
        try {
            server = new LocalServerSocket(SOCKET_ADDRESS);
            while (true) {
                // 一旦有堵塞, 则表示服务器与客户端获得了连接
                if (!connNet){
                    LogUtils.d("服务器等待客户端连接");
                    LocalSocket client = server.accept();
                    connNet = true;
                    LogUtils.d("服务器有客户端连接了");
                    // 处理这次连接
                    new HandlerThread(client);
                }
                sleep(1000);
            }
        } catch (Exception e) {
            LogUtils.e(TAG, "服务器异常: " + e.getMessage());
            if (server != null){
                try {
                    server.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                    server = null;
                }
            }
        }
    }

    private byte[] getBitmapPk(Bitmap bitmap){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] datas = baos.toByteArray();
        int len = datas.length + 4;
        LogUtils.d("服务器 bitmapLen  = " + len);
        byte[] dataPk = new byte[datas.length + 4];
        dataPk[0] = (byte)((len >> 24) & 0xFF);
        dataPk[1] = (byte)((len >> 16) & 0xFF);
        dataPk[2] = (byte)((len >> 8) & 0xFF);
        dataPk[3] = (byte)(len & 0xFF);

        System.arraycopy(datas, 0, dataPk, 4, len - 4);

        return dataPk;
    };

    private class HandlerThread implements Runnable {
        private CamParameter mCamParameter = null;
        private LocalSocket socket;

        public HandlerThread(LocalSocket client) {
            socket = client;
            new Thread(this).start();
        }

        public void run() {
            if (Build.VERSION.SDK_INT >= 9) {
                while (mCamParameter == null) {
                    for (int i = 0; i < CamService.CamNumber; i++) {
                        if ((CamService.camParameters[i] != null && CamService.camParameters[i].IMG_TYPE == CamParameter.FMT_TYPE_H264 && CamService.camParameters[i].DEV_TYPE == CamParameter.DEV_TYPE_USB)) {
                            mCamParameter = CamService.camParameters[i];
                            break;
                        }
                    }
                }
            }

            InputStream input = null;
            OutputStream out = null;
            try {
                input = socket.getInputStream();
                out = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

            byte[] rdata = new byte[1];
//            byte[] wdata1 = new byte[1280 * 720 * 4];
            Mat faceMat = null;
            int len = 0;
            while (connNet) {
                rdata[0] = -1;
                try {
                    len = input.read(rdata);
                } catch (IOException e) {
                    e.printStackTrace();
                    LogUtils.d("服务器读异常 len = " + len);
                }
                if (len <= 0){
                    LogUtils.d("read 失败 客户端异常退出 len = " + len);
                    connNet = false;
                    break;
                }

                if (rdata[0] == 0){
                    synchronized (mCamParameter.videosyn){
                        mCamParameter.mFrameChain[1].put(0, 0, mCamParameter.IMG_DATA);
                        if (!mCamParameter.mFrameChain[1].empty()) {
                            faceMat = mCamParameter.mCameraFrame[1].rgba();

                            Bitmap bitmapFace = Bitmap.createBitmap(mCamParameter.IMG_WIDTH, mCamParameter.IMG_HEIGHT, Bitmap.Config.ARGB_8888);
                            org.opencv.android.Utils.matToBitmap(faceMat, bitmapFace);

                            byte[] datas = getBitmapPk(bitmapFace);

                            if (datas != null) {
                                if (out != null){
                                    LogUtils.d("服务器发送数据 bgr24 len = " + datas.length);
                                    try {
                                        out.write(datas);
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                        LogUtils.d("服务器发送数据 异常 = " + datas.length);
                                        connNet = false;
                                        break;
                                    }
                                }else {
                                    connNet = false;
                                }
                            }
                        }
                    }
                }

                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (socket != null) {
                try {
                    socket.close();
                    socket.shutdownInput();
                    socket.shutdownOutput();
                    LogUtils.d("服务器close ");
                    connNet = false;
                } catch (Exception e) {
                    socket = null;
                    LogUtils.e(TAG,"服务端 finally 异常:" + e.getMessage());
                    connNet = false;
                }
            }
        }
    }
}
